package com.cloudpark.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cloudpark.model.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloudpark.common.mqtt.MqttDTO;
import com.cloudpark.common.mqtt.QueryFeeDTO;
import com.cloudpark.common.mqtt.QueryFeeResultDTO;
import com.cloudpark.common.util.Constants;
import com.cloudpark.common.util.ObjectUtil;
import com.cloudpark.common.util.UuidUtil;
import com.cloudpark.common.util.wechat.WxManagerUtil;
import com.cloudpark.model.vo.Card;
import com.cloudpark.mqtt.MQTTPub;
import com.cloudpark.service.EstateService;
import com.cloudpark.service.MqttMessageService;
import com.cloudpark.service.OrderService;
import com.cloudpark.service.ParkService;
import com.cloudpark.service.PlateService;
import com.cloudpark.service.UserService;

@Controller
@RequestMapping("/wechat")
public class WeChatController {

	private final Logger log = LoggerFactory.getLogger(ApiController.class);
    
    @Autowired
    private UserService userService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private EstateService estateService;
    @Autowired
    private ParkService parkService;
    @Autowired
    private PlateService plateService;
    @Autowired
    private MqttMessageService mqttMessageService;
    
    @RequestMapping(value = "/queryFee", method = RequestMethod.GET)
    public ModelAndView queryFee(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mv = new ModelAndView("wechat/queryFee.jsp");
        String plateNumber = request.getParameter("plateNumber");
    	String uid = request.getParameter("uid");
        String ecode = request.getParameter("ecode");
        return mv;
    }
    
    @RequestMapping(value = "/pay", method = RequestMethod.GET)
    public String pay(HttpServletRequest request, HttpServletResponse response) {
        try {
        	String plateNumber = request.getParameter("plateNumber");
        	String parkCode = request.getParameter("parkCode");
            String ecode = request.getParameter("ecode");
            log.info("pay page receive params: plateNumber = {}, parkCode = {}, ecode = {}", plateNumber, parkCode, ecode);
            // send mqtt message to query fee
            MqttDTO<QueryFeeDTO> mqttDTO = new MqttDTO<QueryFeeDTO>();
            mqttDTO.setCode(Constants.OK);
            mqttDTO.setUuid(UuidUtil.getUUID());
            mqttDTO.setServiceId(Constants.PAY_QUERY_FEE);
            List<QueryFeeDTO> queryFeeDTOs = new ArrayList<QueryFeeDTO>();
            QueryFeeDTO queryFeeDTO = new QueryFeeDTO();
            queryFeeDTO.setPlateNumber(plateNumber);
            queryFeeDTO.setBusinessCode(ecode);
            if (ObjectUtil.isNotBlank(parkCode)) {
            	queryFeeDTO.setParkCode(parkCode);
            }
            queryFeeDTOs.add(queryFeeDTO);
            mqttDTO.setDataItems(queryFeeDTOs);
            
            String sendMessage = JSON.toJSONString(mqttDTO);
    		MqttMessage mqttMessage = new MqttMessage();
    		mqttMessage.setUuid(mqttDTO.getUuid());
    		mqttMessage.setSponsor(Constants.MQTT_SPONSOR_CLOUDPARK);
    		mqttMessage.setSendMessage(sendMessage);
    		mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDIING);
    		mqttMessage.setSendTime(new Date());
    		mqttMessage.setCreatedTime(new Date());
    		mqttMessageService.save(mqttMessage);
    		boolean success = MQTTPub.getSingleton().publish(sendMessage);
    		if (success) {
    			mqttMessage.setSendStatus(Constants.MQTT_STATUS_SENDED);
    			mqttMessageService.update(mqttMessage);
    		}
            
    		String state = mqttDTO.getUuid()+","+ecode;
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
            String redirectUrl = WxManagerUtil.getOAuthCodeUrl(estateWechat.getAppId(), Constants.baseUrl + "wechat/doPay", "snsapi_base", state);
            response.sendRedirect(redirectUrl);
        } catch (Exception e) {
            log.error("come into pay.jsp error", e);
        }
        return null;
    }
    
    @RequestMapping(value = "/doPay", method = RequestMethod.GET)
    public ModelAndView doPay(HttpServletRequest request, HttpServletResponse response) {
    	ModelAndView mv = new ModelAndView("wechat/pay.jsp");
        try {
            String code = request.getParameter("code");
            String state = request.getParameter("state");
            log.info("doPay receive params: code = {}, state = {}", code, state);
            String[] params = state.split(",");
            String uuid = params[0];
            String ecode = params[1];
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
            JSONObject jsonObject = WxManagerUtil.getOpenIdForUrl(code, estateWechat.getAppId(), estateWechat.getAppSecret());
            log.info("user info = " + jsonObject.toJSONString());
            if (null != jsonObject && !jsonObject.containsKey("errcode")) {
                String openId = jsonObject.getString("openid");
                User user = userService.findUserByOpenId(openId);
                log.info(user.toString());
                MqttMessage mqttMessage = mqttMessageService.queryByUuid(uuid);
                log.info(mqttMessage.toString());
                boolean success = false;
                if (null != mqttMessage.getReceiveStatus() && mqttMessage.getReceiveStatus().intValue() == Constants.MQTT_STATUS_RECEIVED) {
                	success = payFeeHandler(estate.getId(), mv, mqttMessage, openId);
                } else {
                	try {
        				long sleepTimes = 2000l;
        				log.info(Constants.PAY_QUERY_FEE + " waiting for mqtt callback result, sleeping "+sleepTimes+" ms");
    					Thread.sleep(sleepTimes);
    				} catch (InterruptedException e) {
    					log.error("thead sleep error", e);
    				}
        			mqttMessage = mqttMessageService.queryById(mqttMessage.getId());
        			log.info(mqttMessage.toString());
        			if (null != mqttMessage.getReceiveStatus() && mqttMessage.getReceiveStatus().intValue() == Constants.MQTT_STATUS_RECEIVED) {
        				success = payFeeHandler(estate.getId(), mv, mqttMessage, openId);
            		}
                }
                if (success) {
                	mv.addObject("ecode", ecode);
                	mv.addObject("uid", user.getId());
                	mv.addObject("orderFlag", Constants.ENABLE);
                } else {
                	log.error("get user order error");
                	mv.addObject("orderFlag", Constants.DISABLE);
                }
            } else {
            	log.error("get user openid error");
            	mv.addObject("orderFlag", Constants.DISABLE);
            }
        } catch (Exception e) {
        	log.error("get user order error", e);
        	mv.addObject("orderFlag", Constants.DISABLE);
        }
        return mv;
    }
    
    /**
     * 公众号提供二维码扫码
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/scanQrcode", method = RequestMethod.GET)
    public ModelAndView scanQrcode(HttpServletRequest request, HttpServletResponse response) {
    	ModelAndView mv = new ModelAndView("wechat/queryToPay.jsp");
        try {
        	String ecode = request.getParameter("ecode");
//            String state = ecode;
//            Estate estate = estateService.queryEstateByCode(ecode);
//            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
//            String openidUrl = WxManagerUtil.getOAuthCodeUrl(estateWechat.getAppId(), Constants.baseUrl + "wechat/doScanQrcode", "snsapi_base", state);
//            response.sendRedirect(openidUrl);
        	mv.addObject("ecode", ecode);
        } catch (Exception e) {
        	log.error("scanQrcode error", e);
        }
        return mv;
    }

//    @RequestMapping(value = "/doScanQrcode", method = RequestMethod.GET)
//    public ModelAndView doScanQrcode(HttpServletRequest request, HttpServletResponse response) {
//        ModelAndView mv = new ModelAndView("wechat/queryToPay.jsp");
//        try {
//            String code = request.getParameter("code");
//            String ecode = request.getParameter("state");
//            log.info("request params code=" + code + ", ecode=" + ecode);
//    Estate estate = estateService.queryEstateByCode(ecode);
//    EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
//            JSONObject jsonObject = WxManagerUtil.getOpenIdForUrl(code, estateWechat.getAppId(), estateWechat.getAppSecret());
//            if (null != jsonObject && !jsonObject.containsKey("errcode")) {
//                String openId = jsonObject.getString("openid");
//                User user = userService.findUserByOpenId(openId);
//                mv.addObject("uid", user.getId());
//                log.info("doScanQrcode openid = " + openId);
//            } else {
//            	log.info("doScanQrcode get openid error");
//            }
//            mv.addObject("ecode", ecode);
//        } catch (Exception e) {
//            log.error("doScanQrcode error", e);
//        }
//        return mv;
//    }
    
    private boolean payFeeHandler(Long estateId, ModelAndView mv, MqttMessage mqttMessage, String openId) {
    	if (ObjectUtil.isNotBlank(mqttMessage.getReceiveMessage())) {
    		log.info("mq receive message = " + mqttMessage.getReceiveMessage());
    		JSONObject jsonObject = JSON.parseObject(mqttMessage.getReceiveMessage());
	        String dataItems = jsonObject.getString("dataItems");
	        log.info("mq receive message dataitems = " + dataItems);
	        List<QueryFeeResultDTO> queryFeeResultDTOs = JSON.parseArray(dataItems, QueryFeeResultDTO.class);
	        if (ObjectUtil.isNotBlank(queryFeeResultDTOs)) {
	        	QueryFeeResultDTO resultQueryFeeDTO = queryFeeResultDTOs.get(0);
	        	ParkOrderTemp orderTemp = new ParkOrderTemp();
	        	orderTemp.setOpenId(openId);
	        	orderTemp.setOrderNo(UuidUtil.getTCOrderNo());
	        	orderTemp.setPlateNumber(resultQueryFeeDTO.getPlateNumber());
	        	orderTemp.setParkCode(resultQueryFeeDTO.getParkCode());
	        	orderTemp.setEstateId(estateId);
	        	orderTemp.setPayableFee(resultQueryFeeDTO.getPayableFee());
	        	orderTemp.setDiscountFee(resultQueryFeeDTO.getDiscountFee());
	        	orderTemp.setPaidFee(resultQueryFeeDTO.getPaidFee());
	        	orderTemp.setEnterTime(resultQueryFeeDTO.getEnterTime());
	        	orderTemp.setLeaveTime(resultQueryFeeDTO.getLeaveTime());
	        	orderTemp.setUseTime(resultQueryFeeDTO.getUseTime());
	        	orderTemp.setType(resultQueryFeeDTO.getType());
	        	orderTemp.setPayType(Constants.PAY_BY_WECHAT);
	        	orderTemp.setPayChannel(Constants.PAY_CHANNEL_1);
	        	orderTemp.setCreatedTime(new Date());
	        	log.info(orderTemp.toString());
	        	orderService.saveParkOrderTemp(orderTemp);
	        	mv.addObject("order", orderTemp);
	        	// park info
	        	Park park = parkService.queryByParkCode(resultQueryFeeDTO.getParkCode());
	        	mv.addObject("park", park);
	        	log.info(park.toString());
	        	return true;
	        } else {
	        	log.info("mq receive message dataitems is empty ");
	        }
    	} else {
    		log.info("mq receive message is empty");
    	}
		return false;
	}
    
    /**
     * 我的月卡
     * @param request
     * @param response
     * @return
     */
	@RequestMapping(value = "/card", method = RequestMethod.GET)
    public ModelAndView card(HttpServletRequest request, HttpServletResponse response) {
		try {
			String ecode = request.getParameter("ecode");
	        String state = ecode;
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
	        String redirectUrl = WxManagerUtil.getOAuthCodeUrl(estateWechat.getAppId(), Constants.baseUrl + "wechat/doCard", "snsapi_base", state);
	        response.sendRedirect(redirectUrl);
		} catch (Exception e) {
			log.error("come into card page error", e);
		}
        return null;
//		ModelAndView mv = new ModelAndView("wechat/card.jsp");
//		return mv;
    }
	
	@RequestMapping(value = "/doCard", method = RequestMethod.GET)
    public ModelAndView doCard(HttpServletRequest request, HttpServletResponse response) {
    	ModelAndView mv = new ModelAndView("wechat/card.jsp");
        try {
            String code = request.getParameter("code");
            String state = request.getParameter("state");
            log.info("doCard receive params: state = {} ",state);
            String ecode = state;
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
            JSONObject jsonObject = WxManagerUtil.getOpenIdForUrl(code, estateWechat.getAppId(), estateWechat.getAppSecret());
            if (null != jsonObject && !jsonObject.containsKey("errcode")) {
                String openId = jsonObject.getString("openid");
                User user = userService.findUserByOpenId(openId);
                mv.addObject("uid", user.getId());
                mv.addObject("ecode", ecode);
            } else {
            	log.info("get openid with user in card page error");
            }
        } catch (Exception e) {
        	log.error("do come into card page error", e);
        }
        return mv;
    }
	
	/**
     * 单张月卡管理界面
     * @param request
     * @param response
     * @return
     */
	@RequestMapping(value = "/cardManage", method = RequestMethod.GET)
    public ModelAndView cardManage(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView mv = new ModelAndView("wechat/cardManage.jsp");
		try {
			String uid = request.getParameter("uid");
			String ecode = request.getParameter("ecode");
			String plateNumber = request.getParameter("plateNumber");
			String parkCode = request.getParameter("parkCode");
			String deadlineDate = request.getParameter("deadlineDate");
			String price = request.getParameter("price");
			String status = request.getParameter("status");
			String parkName = request.getParameter("parkName");
			log.info("card manage receive params, uid = " + uid + ", ecode = " + ecode + ", plateNumber = " + plateNumber
					+ ", parkCode = " + parkCode + ", deadlineDate = " + deadlineDate + ", price = " + price
					+ ", status = " + status + ", parkName = " + parkName);
			// 获取月卡信息
            Card card = new Card();
            card.setPlateNumber(plateNumber);
            card.setParkCode(parkCode);
            card.setDeadlineDate(deadlineDate);
            card.setPrice(Double.valueOf(price));
            card.setStatus(Integer.valueOf(status));
            card.setParkName(parkName);
            // 获取停车场信息
            Park park = parkService.queryByParkCode(card.getParkCode());
            mv.addObject("card", card);
            mv.addObject("park", park);
			
            mv.addObject("uid", uid);
            mv.addObject("ecode", ecode);
            
//	        Card card = new Card();
//	        card.setStatus(1);
//	        card.setDeadlineDate("2017-12-22");
//	        card.setPrice(12.03);
//	        card.setPlateNumber("粤B12345");
//	        Park park = new Park();
//	        park.setName("dfsjflsjfls哈哈");
//	        mv.addObject("card", card);
//	        mv.addObject("park", park);
		} catch (Exception e) {
			log.error("come into card manage page error", e);
		}
        return mv;
    }
	
	@RequestMapping(value = "/cardOrder", method = RequestMethod.GET)
    public ModelAndView cardOrder(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mv = new ModelAndView("wechat/cardOrder.jsp");
        String uid = request.getParameter("uid");
		String ecode = request.getParameter("ecode");
		String plateNumber = request.getParameter("plateNumber");
		String parkCode = request.getParameter("parkCode");
		 mv.addObject("plateNumber", plateNumber);
         mv.addObject("parkCode", parkCode);
         mv.addObject("uid", uid);
         mv.addObject("ecode", ecode);
        return mv;
    }
    
    @RequestMapping(value = "/order", method = RequestMethod.GET)
    public ModelAndView order(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mv = new ModelAndView("wechat/order.jsp");
        return mv;
    }
    
    /**
     * 我的车辆
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/vehicle", method = RequestMethod.GET)
    public String vehicle(HttpServletRequest request, HttpServletResponse response) {
        try {
            String ecode = request.getParameter("ecode");
    		String state = ecode;
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
            String redirectUrl = WxManagerUtil.getOAuthCodeUrl(estateWechat.getAppId(), Constants.baseUrl + "wechat/doVehicle", "snsapi_base", state);
            response.sendRedirect(redirectUrl);
        } catch (Exception e) {
            log.error("come into pay.jsp error", e);
        }
        return null;
    }
    
    @RequestMapping(value = "/doVehicle", method = RequestMethod.GET)
    public ModelAndView doVehicle(HttpServletRequest request, HttpServletResponse response) {
    	ModelAndView mv = new ModelAndView("wechat/vehicle.jsp");
    	try {
    		String code = request.getParameter("code");
            String ecode = request.getParameter("state");
            log.info("request params code=" + code + ", state=" + ecode);
            Estate estate = estateService.queryEstateByCode(ecode);
            EstateWechat estateWechat = estateService.queryEstateWechatByEstateId(estate.getId());
            JSONObject jsonObject = WxManagerUtil.getOpenIdForUrl(code, estateWechat.getAppId(), estateWechat.getAppSecret());
            log.info("user info = " + jsonObject.toJSONString());
            if (null != jsonObject && !jsonObject.containsKey("errcode")) {
                String openId = jsonObject.getString("openid");
                User user = userService.findUserByOpenId(openId);
                mv.addObject("uid", user.getId());
            } else {
            	log.info("vehicle get user info error");
            }
		} catch (Exception e) {
			log.error("vehicle error" , e);
		}
        return mv;
    }
}
